from pyjamas.ui import Button, RootPanel, Label, SimplePanel, PopupPanel, Grid
from pyjamas import Window
from pyjamas.ui import Image, HTML, HTMLPanel, VerticalPanel, HorizontalPanel, FocusPanel, TextBox
from Canvas import Canvas, CanvasImage, ImageLoadListener
from pyjamas.Timer import Timer
from math import floor, cos, sin
from pyjamas import DOM
from pyjamas.Tooltip import Tooltip, TooltipListener

class NumericTextBox(TextBox):
    
    def __init__(self):
        TextBox.__init__(self)
        DOM.setEventListener(self.getElement(), self)
        self.sinkEvents(Event.ONKEYPRESS)
    
    def onBrowserEvent(self, event):
        typeofEv = DOM.eventGetType(event)
        if not typeofEv == "keypress":
            return True
        charCode = DOM.eventGetKeyCode(event)
        if charCode == 44:
            return True
        if charCode == 46:
            return True
        if charCode < 48 or charCode > 57:
            JS("""
               if (event.cancelBubble)
                event.cancelBubble = true;
               if (event.preventDefault)
                event.preventDefault();
               if (event.stopPropagation)
                event.stopPropagation();
            """)
            event.returnValue = False
            return False
        else:
            return True
        
def navLanguage():
    JS("""
       if (navigator.userLanguage)
        return navigator.userLanguage.substring(0, 2);
       if (navigator.language) 
        return navigator.language.substring(0, 2);
       return 'en';
       """)
    
class Calendar(FocusPanel):
    daysLabels_es = ["Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab"]
    monthsNames_es = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Setiembre",
                   "Octubre", "Noviembre", "Diciembre"]
    daysLabels_en = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
    monthsNames_en = ["January", "February", "March", "April", "May", "June", "July", "August", "September",
                   "October", "November", "December"]
    monthsDays = [31,28,31,30,31,30,31,31,30,31,30,31]
    daysLabels = {'es': Calendar.daysLabels_es, 'en': Calendar.daysLabels_en}
    monthsNames = {'es': Calendar.monthsNames_es , 'en': Calendar.monthsNames_en}
    otherLabels = {'es': {'lblToday': 'Hoy', 'lblClose': 'Cerrar', 'ttBack10y': 'Atrás 10 a&#241;os',
                          'ttBack1y': 'Atr&#225;s 1 a&#241;o', 'ttBack1m': 'Atr&#225;s 1 mes', 'ttFwd1m': 'Adelante 1 mes',
                          'ttFwd1y': 'Adelante 1 a&#241;o', 'ttFwd10y': 'Adelante 10 a&#241;os'},
        'en': {'lblToday': 'Today', 'lblClose': 'Close', 'ttBack10y': 'Back 10 years', 'ttBack1y': 'Back 1 year',
               'ttBack1m': 'Back 1 month', 'ttFwd1m': 'Forward 1 month',
                          'ttFwd1y': 'Forward 1 year', 'ttFwd10y': 'Forward 10 years'}}
    
    def isLeapYear(self):
        if self.year % 4:    
            return False
        if not self.year % 100:
            if not self.year % 400:
                return True
            else:
                return False
        else:
            return True

    def setPopupPosition(self, left, top):
        if left < 0:
            left = 0
        if top < 0:
            top = 0

        element = self.getElement()
        DOM.setStyleAttribute(element, "left", left + "px")
        DOM.setStyleAttribute(element, "top", top + "px")
        
    def onMouseDown(self, sender, x, y):
        if sender == self.lblCurrentMonthYear:
            self.dragging = True
            DOM.setCapture(self.lblCurrentMonthYear.getElement())
            self.dragStartX = x
            self.dragStartY = y
        else:
            FocusPanel.onMouseDown(self, sender, x, y)
            
    def onMouseEnter(self, sender):
        pass

    def onMouseLeave(self, sender):
        pass

    def onMouseMove(self, sender, x, y):
        if self.dragging:
            absX = x + self.getAbsoluteLeft()
            absY = y + self.getAbsoluteTop()
            self.setPopupPosition(absX - self.dragStartX, absY - self.dragStartY)

    def onMouseUp(self, sender, x, y):
        if sender == self.lblCurrentMonthYear:
            self.dragging = False
            DOM.releaseCapture(self.lblCurrentMonthYear.getElement())
        else:
            FocusPanel.onMouseUp(self, sender, x, y)
            
            
    def __init__(self, visible = False, text = "", textbox = None, date = None, dateSep = "-", firstDayOfWeek = 1, 
                 backColor = "#D4D0C8", autoHide = True):
        
        FocusPanel.__init__(self)
        
#        Window.alert(navLanguage())
        self.monthsNames = Calendar.monthsNames[navLanguage()]
        self.daysLabels = Calendar.daysLabels[navLanguage()]
        self.otherLabels = Calendar.otherLabels[navLanguage()]
        
        self.monthChanged = True
        
        self.dragging = False
        self.dragStartX = 0
        self.dragStartY = 0
        
        self.year = 0
        self.month = 0
        self.day = 0
        self.dayOfWeek = 0
        self.fdomDayOfWeek = 0
        self.todayYear = 0
        self.todayMonth = 0
        self.todayDay = 0
        
        if firstDayOfWeek > 1:
            firstDayOfWeek = 1
        if firstDayOfWeek < 0:
            firstDayOfWeek = 0
        self.firstDayOfWeek = firstDayOfWeek
        self.dateSep = dateSep
        self.text = text
        self.textbox = textbox
        
        self.backColor = backColor
        self.autoHide = autoHide

        self.setWidth("19%")
        
        self.vp = VerticalPanel()
        
        self.titlePanel = HorizontalPanel()
        fp = FocusPanel()
        fp.addMouseListener(TooltipListener(self.otherLabels['ttBack10y']))
        self.btnBack10Years = Button("&lt;&lt;&lt;", getattr(self, "minus10Years"))
        fp.add(self.btnBack10Years)
        self.titlePanel.add(fp)
        fp = FocusPanel()
        fp.addMouseListener(TooltipListener(self.otherLabels['ttBack1y']))
        self.btnBackYear = Button("&lt;&lt;", getattr(self, "minusYear"))
        fp.add(self.btnBackYear)
        self.titlePanel.add(fp)
        fp = FocusPanel()
        fp.addMouseListener(TooltipListener(self.otherLabels['ttBack1m']))
        self.btnBackMonth = Button("&lt;", getattr(self, "minusMonth"))
        fp.add(self.btnBackMonth)
        self.titlePanel.add(fp)
        self.lblCurrentMonthYear = Label("")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "marginLeft", "1px")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "marginRight", "1px")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "paddingLeft", "10px")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "paddingRight", "10px")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "color", "#0D4B70")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "backgroundColor", "rgb(255,255,255)")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "fontSize", "small")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "cursor", "move")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "width", "8em")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "textAlign", "center")
        DOM.setStyleAttribute(self.lblCurrentMonthYear.getElement(), "verticalAlign", "middle")
        self.titlePanel.add(self.lblCurrentMonthYear)
        fp = FocusPanel()
        fp.addMouseListener(TooltipListener(self.otherLabels['ttFwd1m']))
        self.btnNextMonth = Button("&gt;", getattr(self, "plusMonth"))
        fp.add(self.btnNextMonth)
        self.titlePanel.add(fp)
        fp = FocusPanel()
        fp.addMouseListener(TooltipListener(self.otherLabels['ttFwd1y']))
        self.btnNextYear = Button("&gt;&gt;", getattr(self, "plusYear"))
        fp.add(self.btnNextYear)
        self.titlePanel.add(fp)
        fp = FocusPanel()
        fp.addMouseListener(TooltipListener(self.otherLabels['ttFwd10y']))
        self.btnNext10Years = Button("&gt;&gt;&gt;", getattr(self, "plus10Years"))
        fp.add(self.btnNext10Years)
        self.titlePanel.add(fp)
                               
        self.vp.add(self.titlePanel)
        
        self.daysPanel = SimplePanel()
        self.vp.add(self.daysPanel)
        
        proxy = self

        def autoCerrar():
            proxy.setVisible(False)
            
        def irAHoy():
            strDate = "%d%s%d%s%d" % (proxy.todayYear, proxy.dateSep, proxy.todayMonth + 1, proxy.dateSep, proxy.todayDay)
            if proxy.todayMonth != proxy.month or proxy.todayYear != proxy.year:
                proxy.monthChanged = True
            proxy.setDate(strDate)

        id1 = HTMLPanel.createUniqueId()
        id2 = HTMLPanel.createUniqueId()
        self.bottomPanel = HTMLPanel("<div style='text-align: right;'><span id=" + id2 + "><span id=" + id1 + "></div>")            
        self.btnToday = Button(self.otherLabels['lblToday'], irAHoy)
        self.bottomPanel.add(self.btnToday, id1)
        self.btnClose = Button(self.otherLabels['lblClose'], autoCerrar)
        self.bottomPanel.add(self.btnClose, id2)
        self.btnToday.setWidth("50%")
        self.btnClose.setWidth("50%")
        self.vp.add(self.bottomPanel)
        
        DOM.setStyleAttribute(self.vp.getElement(), "border", "1px solid")
        DOM.setStyleAttribute(self.vp.getElement(), "padding", "2px")

        self.setDate(date)

        JS("""
           var d = new Date()
           var todayYear = d.getYear()
           if (todayYear < 1900)
            todayYear += 1900;
           var todayMonth = d.getMonth();
           var todayDay = d.getDate();
           var todayDayOfWeek = d.getDay();
           """)
        
        self.todayYear = todayYear
        self.todayMonth = todayMonth
        self.todayDay = todayDay
        self.todayDayOfWeek = todayDayOfWeek
        
        DOM.setStyleAttribute(self.vp.getElement(), "backgroundColor", self.backColor)
        self.setWidget(self.vp)
        
        wi = self.vp.getOffsetWidth()
        
        DOM.setStyleAttribute(self.getElement(), "position", "absolute")
        
        
        self.lblCurrentMonthYear.addMouseListener(self)
        self.setVisible(visible)
    
    def setDestination(self, textbox):
        self.textbox = textbox
        
    def _rechargeDate(self):
        strDate = "%d%s%d%s%d" % (self.year, self.dateSep, self.month + 1, self.dateSep, self.day)
        self.setDate(strDate)
        
    def plus10Years(self):
        self.year += 10
        self.monthChanged = True
        self._rechargeDate()
        
    def plusYear(self):
        self.year += 1
        self.monthChanged = True
        self._rechargeDate()
        
    def minus10Years(self):
        self.year -= 10
        self.monthChanged = True
        self._rechargeDate()
        
    def minusYear(self):
        self.year -= 1
        self.monthChanged = True
        self._rechargeDate()

    def plusMonth(self):
        self.month += 1
        if self.month > 11:
            self.year += 1
            self.month = 0
        self.monthChanged = True
        self._rechargeDate()
        
    def minusMonth(self):
        self.month -= 1
        if self.month < 0:
            self.month = 11
            self.year -= 1
        self.monthChanged = True
        self._rechargeDate()
        
    def doSomething(self, sender):
        if self.textbox:
            btnvalue = sender.getText()
            texto = "%s %d" % (self.toString(), btnvalue)
            self.textbox.setText(texto)
        self.setVisible(False)
        
    def setDate(self, date):
        year = None
        month = None
        day = None
        dayOfWeek = None
        
        if not date:
            JS("""
               date = new Date();
               year = date.getYear();
               if (year < 1900)
                year += 1900;
               month = date.getMonth();
               day = date.getDate();
               dayOfWeek = date.getDay();
               """)
        else:
            arr = date.split(self.dateSep)
            if arr[0].startswith('0'):
                arr[0] = arr[0][1:]
            if arr[1].startswith('0'):
                arr[1] = arr[1][1:]
            if arr[2].startswith('0'):
                arr[2] = arr[2][1:]
            year = int(arr[0])
            month = int(arr[1]) - 1
            day = int(arr[2])
            JS("""
               newdate = new Date(year, month, day);
               dayOfWeek = newdate.getDay();
               """)
        
        self.year = year
        self.month = month
        self.day = day
        self.dayOfWeek = dayOfWeek

        JS("""
           d = new Date(year, month, 1)
           var fdow = d.getDay();
           """)
        
        fdow -= self.firstDayOfWeek
        if fdow < 0:
            fdow = len(self.daysLabels) + fdow
            
        self.fdomDayOfWeek = fdow
        
        if self.monthChanged:
            self.drawDays()
            self.monthChanged = False
        
        self.paintDays()
        
        self.lblCurrentMonthYear.setText("%s %d" % (self.monthsNames[self.month], self.year))
        if self.textbox:
                self.textbox.setText(self.toString())

    def drawDays(self):
        totalDays = self.getTotalDrawDays()
        rows = totalDays / 7
        if totalDays % 7:
            rows += 1
        cols = 7
        self.grid = Grid(rows+1, cols)
        grid = self.grid
        grid.setWidth("100%")
        
        cellformatter = grid.getCellFormatter()
        DOM.setAttribute(grid.getElement(), "border", "1")
        DOM.setStyleAttribute(grid.getElement(), "borderCollapse", "collapse")
        DOM.setStyleAttribute(grid.getElement(), "cursor", "pointer")
        grid.addTableListener(self)
        DOM.setStyleAttribute(grid.getElement(), "backgroundColor", self.backColor)

        
        for c in range(self.firstDayOfWeek, cols):
            grid.setText(0, c-self.firstDayOfWeek, self.daysLabels[c])
            DOM.setStyleAttribute(cellformatter.getElement(0, c-self.firstDayOfWeek), "backgroundColor", "#0D4B70")
            DOM.setStyleAttribute(cellformatter.getElement(0, c-self.firstDayOfWeek), "color", "white")
            DOM.setStyleAttribute(cellformatter.getElement(0, c-self.firstDayOfWeek), "textAlign", "center")
            DOM.setStyleAttribute(cellformatter.getElement(0, c-self.firstDayOfWeek), "fontFamily", "Courier")
        if self.firstDayOfWeek:
            for c in range(0, self.firstDayOfWeek):
                grid.setText(0, c + cols - 1, self.daysLabels[c])
                DOM.setStyleAttribute(cellformatter.getElement(0, c + cols -1), "backgroundColor", "#0D4B70")
                DOM.setStyleAttribute(cellformatter.getElement(0, c + cols -1), "color", "white")
                DOM.setStyleAttribute(cellformatter.getElement(0, c + cols -1), "textAlign", "center")
                DOM.setStyleAttribute(cellformatter.getElement(0, c + cols -1), "fontFamily", "Courier")
            
        counter = 0
            
        for r in range(1, rows + 1):
            for c in range(cols):
                if counter  < self.fdomDayOfWeek or  counter >= totalDays:
                    grid.setText(r,c,"")
                else:
                    grid.setText(r,c, str((counter + 1)  - self.fdomDayOfWeek))
                    DOM.setStyleAttribute(cellformatter.getElement(r, c), "textAlign", "center")
                counter += 1

        self.daysPanel.setWidget(grid)
    
    def paintDays(self):
        formatter = self.grid.getCellFormatter()
        for r in range(1, self.grid.getRowCount()):
            for c in range(7):
                texto = self.grid.getText(r, c)
                if texto != "":
                    num = int(texto)
                    if num == self.day:
                        DOM.setStyleAttribute(formatter.getElement(r, c), "backgroundColor", "white")
                    else:
#                        DOM.setStyleAttribute(formatter.getElement(r, c), "backgroundColor", self.backColor)
                        if num == self.todayDay and self.month == self.todayMonth and self.year == self.todayYear:
                            DOM.setStyleAttribute(formatter.getElement(r, c), "color", "white")
                            DOM.setStyleAttribute(formatter.getElement(r, c), "backgroundColor", "rgb(0,192,0)")
                        else:
                            DOM.setStyleAttribute(formatter.getElement(r, c), "color", "black")
                            DOM.setStyleAttribute(formatter.getElement(r, c), "backgroundColor", self.backColor)
    
    def onCellClicked(self, grid, row, col):
        texto = grid.getText(row, col)
        if texto == "" or row == 0:
            return
        self.day = int(texto)
        self._rechargeDate()
        if self.autoHide:
            self.setVisible(False)
        
    
    def getTotalDrawDays(self):
        monthDays = Calendar.monthsDays[self.month]
        if self.isLeapYear() and self.month == 1:
            monthDays += 1
        monthDays += self.fdomDayOfWeek
        return monthDays
    
    def toString(self):
        return "%d%s%0.2d%s%0.2d" % (self.year, self.dateSep, self.month + 1, self.dateSep, self.day)
    
    def __str__(self):
        return self.__repr__()

class DateTextBox(HorizontalPanel):
    
    def __init__(self):
        HorizontalPanel.__init__(self)
        self.tb = TextBox()
        self.calendar = Calendar(textbox = self.tb)
        self.add(self.tb)
        self.add(self.calendar)
        thiss = self
        def showCalendar():
            thiss.calendar.setVisible(True)
        self.btn = Button("...", showCalendar)
#        self.add(self.btn)
        y = self.getAbsoluteTop() + self.getOffsetHeight()
        x = self.getAbsoluteLeft()
        self.calendar.setPopupPosition(x, y)
        
        self.tb.addClickListener(showCalendar)
        DOM.setAttribute(self.tb.getElement(), "readOnly", "readonly")
    
    def getMaxLength(self):
        return self.tb.getMaxLength()
    
    def setMaxLength(self, length):
        self.tb.setMaxLength(length)
        
    def getVisibleLength(self):
        return self.tb.getVisibleLength()
    
    def setVisibleLength(self, length):
        self.tb.setVisibleLength(length)

    def getText(self):
        return self.tb.getText()
    
    def setText(self, text):
        self.tb.setText(text)
        self.calendar.setDate(text)
        
        
    
class SolarCanvas(Canvas):
    def __init__(self, img_url):
        Canvas.__init__(self, 200, 200)
        self.clock = CanvasImage(img_url)
        self.width = 100
        self.height = 100
        
        self.loader = ImageLoadListener(self)
        self.loader.add(self.clock)
        
        self.isActive = True
        self.onTimer()

    def onLoad(self):
        el = self.clock.getElement()
        self.width = DOM.getAttribute(el, "width")
        self.height = DOM.getIntAttribute(el, "height")
        self.setWidth("%dpx" % self.width)
        self.setHeight("%dpx" % self.height)

    def onTimer(self):
        if not self.isActive:
            return
        
        Timer(1000, self)
        self.draw()

    def getTimeSeconds(self):
        JS("""
        var x = new Date();
        return x.getSeconds();
        """)

    def getTimeMinutes(self):
        JS("""
        var x = new Date();
        return x.getMinutes();
        """)

    def getTimeHours(self):
        JS("""
        var x = new Date();
        return x.getHours();
        """)

    def getTimeMilliseconds(self):
        JS("""
        var x = new Date();
        return x.getMilliseconds();
        """)

    def draw(self):
        pi = 3.14159265358979323
        if not self.loader.isLoaded():
            return
        
        self.context.globalCompositeOperation = 'destination-over'

        # clear canvas
        self.context.clearRect(0,0,self.width,self.height) 
        
        self.context.save()
        self.context.fillStyle = 'rgba(0,0,0,0.4)'
        self.context.strokeStyle = 'rgba(0,153,255,0.4)'
        self.context.translate(self.width/2,self.height/2)
        
        secs = self.getTimeSeconds()
        mins = self.getTimeMinutes() + secs / 60.0
        hours = self.getTimeHours() + mins / 60.0

        # Seconds
        self.context.save()
        self.context.fillStyle = 'rgba(255,0,0,0.4)'
        self.context.rotate( ((2*pi)/60)*secs + pi)
        self.context.fillRect(-1,-(self.width * 0.04),2, self.width * 0.38) 
        self.context.restore()
        
        # Minutes
        self.context.save()
        self.context.rotate( ((2*pi)/60)*mins + pi)
        self.context.fillRect(-1,-1,3,self.width * 0.35) 
        self.context.restore()
        
        # Hours
        self.context.save()
        self.context.rotate( ((2*pi)/12)*hours + pi)
        self.context.fillRect(-2,-2,4,self.width * 0.2) 
        self.context.restore()
        
        self.context.restore()
        
        self.context.drawImage(self.clock,0,0)


class RoundPanel(HTMLPanel):
    def __init__(self, html, borderColor = None, bgColor = "#ffffff", cornerSize = "small"):
        if not borderColor:
            borderColor = bgColor
        if cornerSize.lower() != "small":
            templ = """
                <b class="b00f" style="border-color: @bc; background: @bc;"></b>
                <b class="b0f" style="border-color: @bc; background: @bg;"></b>
                <b class="b1f" style="border-color: @bc; background: @bg;"></b>
            """
        else:
            templ = """<b class="b1f" style="border-color: @bc; background: @bc;"></b>"""
        templ += """
                <b class="b2f" style="border-color: @bc; background: @bg;"></b>
                <b class="b3f" style="border-color: @bc; background: @bg;"></b>
                <b class="b4f" style="border-color: @bc; background: @bg;"></b>
                    <div class="contentf" style="border-color: @bc; background: @bg;">
                        <div style="padding: 0.5em;">
                            @2
                        </div>
                    </div>
                <b class="b4f" style="border-color: @bc; background: @bg;"></b>
                <b class="b3f" style="border-color: @bc; background: @bg;"></b>
                <b class="b2f" style="border-color: @bc; background: @bg;"></b>
            """
        if cornerSize.lower() != "small":
            templ += """
                <b class="b1f" style="border-color: @bc; background: @bg;"></b>
                <b class="b0f" style="border-color: @bc; background: @bg;"></b>
                <b class="b00f" style="border-color: @bc; background: @bc;"></b>        
            """
        else:
            templ += """<b class="b1f" style="border-color: @bc; background: @bc;"></b>"""
            
        newhtml = templ.replace("@2", html)
        newhtml = newhtml.replace("@bc", borderColor)
        newhtml = newhtml.replace("@bg", bgColor)
        
        HTMLPanel.__init__(self, newhtml)
        